/*
 * @(#)FindFoldersRunner.java
 * Date 2013-09-04
 * Version 1.0
 * Author Jim Horner
 * Copyright (c)2012
 */


package us.hornerscorners.lamppost.registry.query.es;

import java.util.HashMap;
import java.util.Map;

import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import us.hornerscorners.lamppost.ihecommon.config.IHEConfig;
import us.hornerscorners.lamppost.ihecommon.config.TestHack;

import us.hornerscorners.lamppost.ihecommon.service.ElasticSearchSource;

import us.hornerscorners.lamppost.model.common.PersistableModelType;

import us.hornerscorners.lamppost.registry.constant.QueryField;
import us.hornerscorners.lamppost.registry.constant.QuerySlotName;

import us.hornerscorners.lamppost.registry.model.QueryRequest;

import us.hornerscorners.lamppost.registry.transformer.model.CodedElementTransformer;
import us.hornerscorners.lamppost.registry.transformer.model.PatientIdentifierTransformer;


/**
 * Class description
 *
 *
 * @version        v1.0, 2013-09-04
 * @author         Jim Horner
 */
public class FindFoldersRunner extends AbstractQueryRunner {

    /** Field description */
    private final Logger logger = LoggerFactory.getLogger(getClass());

    /**
     * Constructs ...
     *
     *
     * @param config
     * @param elasticSearchSource
     * @param codedElementTransformer
     * @param patientIdentifierTransformer
     */
    public FindFoldersRunner(IHEConfig config, ElasticSearchSource elasticSearchSource,
                             CodedElementTransformer codedElementTransformer,
                             PatientIdentifierTransformer patientIdentifierTransformer) {

        super(config, elasticSearchSource, codedElementTransformer,
              patientIdentifierTransformer);

    }

    /**
     * Method description
     *
     *
     * @param request
     *
     * @return
     */
    @Override
    public Map<PersistableModelType, QueryBuilder> createQuery(QueryRequest request) {

        Map<PersistableModelType, QueryBuilder> result = new HashMap<>();

        BoolQueryBuilder query = QueryBuilders.boolQuery();

        result.put(PersistableModelType.Folder, query);

        // availability status (required)
        query.must(createStringQuery(request, QuerySlotName.XDSFolderStatus,
                                     QueryField.FolderAvailabilityStatus));

        // patient id
        if (request.hasValues(QuerySlotName.XDSFolderPatientId)) {

            query.must(createPatientIdentifierQuery(request,
                    QuerySlotName.XDSFolderPatientId, QueryField.FolderPatientIdRoot,
                    QueryField.FolderPatientIdExtension));
        }

        // last update time

        if (request.hasValues(QuerySlotName.XDSFolderLastUpdateTimeFrom)
                || request.hasValues(QuerySlotName.XDSFolderLastUpdateTimeTo)) {

            if (getRegistryServiceConfig().useTestHack(TestHack.XDS11899)) {

                // NOTE Test 11899 (2013-10-11) fails, it sends local time
                logger.warn("Using TestHack {}", TestHack.XDS11899);

                query.must(
                    createLocalTimeQuery(
                        request, QuerySlotName.XDSFolderLastUpdateTimeFrom,
                        QuerySlotName.XDSFolderLastUpdateTimeTo,
                        QueryField.FolderLastUpdateTime));

            } else {

                query.must(createTimeQuery(request,
                                           QuerySlotName.XDSFolderLastUpdateTimeFrom,
                                           QuerySlotName.XDSFolderLastUpdateTimeTo,
                                           QueryField.FolderLastUpdateTime));
            }
        }

        // code list
        if (request.hasValues(QuerySlotName.XDSFolderCodeList)) {

            query.must(createCodedElementQuery(request, QuerySlotName.XDSFolderCodeList,
                                               QueryField.FolderCodeListCode,
                                               QueryField.FolderCodeListScheme));
        }

        if (request.hasValues(QuerySlotName.XDSFolderCodeListScheme)) {

            query.must(createStringQuery(request, QuerySlotName.XDSFolderCodeListScheme,
                                         QueryField.FolderCodeListScheme));
        }

        return result;

    }
}
